{-# LANGUAGE FlexibleContexts #-}

module Main where

import Control.Monad.Loops
import Control.Monad.Random
import Control.Monad.State.Lazy
import Data.Bifunctor (bimap, second)
import Data.Text.Prettyprint.Doc
import Data.Text.Prettyprint.Doc.Render.String
import Options.Applicative

import qualified Data.HashSet as HS

import Game.Dusk.Tarot.Card

main :: IO ()
main = do
  i <- execParser opts
  cardoes <- evalRandIO . flip evalStateT HS.empty . cards $ i
  putStrLn .
    renderString .
    layoutPretty defaultLayoutOptions .
    vcat .
    fmap
      ((\(x, y) -> (x <> colon) <+> y) .
       bimap pretty pretty . second GameEffect . join (,)) $
    cardoes
  where
    opts =
      info
        (intParser <**> helper)
        (fullDesc <>
         progDesc
           "Generate a SIZE-card tarot spread for After Sundown karmic advancement" <>
         header "dusk-tarot - a karmic advancement generator")

intParser :: Parser Int
intParser =
  argument
    auto
    (metavar "SIZE" <>
     help "How many cards you want drawn. Should be a positive integer.")

cards :: (MonadRandom m, MonadState (HS.HashSet Card) m) => Int -> m [Card]
cards i =
  whileM
    (do s <- get
        return (HS.size s < i))
    getCard
  where
    getCard = do
      s <- get
      c <- getRandom
      if c `elem` s
        then getCard
        else do
          modify (HS.insert c)
          return c
